Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timeprovider advance multiple invocations #4022

Merged

Conversation

egil
Copy link
Contributor

@egil egil commented May 30, 2023

This fixes #3995. These are the changes I have included:

  1. The FakeTimeProviderTimer.Waiter now tracks when a WakeupTime was scheduled. It does this to ensure that the callbacks are invoked in the order they are scheduled in.
  2. FakeTimeProviderTimer now triggers callbacks one at a time, and allows their callbacks to add reschedule themselves or influence other timers/create new timers.
  3. FakeTimeProvider exposes an Epoch property, which represents the initial start time when the time provider was instantiated. It is a useful value to have available during testing, e.g. if you have to call SetUtcNow multiple times during a test, and the value you are setting is changed in relation to the start time/epoch. It tends to lead to easier-to-understand test code in my experience.
    I also changed the ctor argument startTime on FakeTimeProvider to epoch to match the name of the added property.
  4. Changed Advance() and SetUtcNow() to prevent moving time back.
Microsoft Reviewers: Open in CodeFlow

@ghost ghost assigned egil May 30, 2023
@egil egil force-pushed the 3995-timeprovider-advance-multiple-invocations branch from 6e06690 to d1abbb4 Compare May 30, 2023 22:18
@egil
Copy link
Contributor Author

egil commented May 30, 2023

I didn't want to change too much of the existing implementation, but an alternative approach to implementing this I've used in my ManualTimeProvider is to only hold waiters in the FakeTimeProvider.Waiters collection in while their timer has a scheduled callback, and keep the waiters sorted by WakeupTime. That would eliminate the need for the Waiter.ScheduledOn property but would be a bigger change to the existing implementation.

@egil egil removed their assignment May 31, 2023
@ghost ghost assigned egil May 31, 2023
Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few nits

@RussKie RussKie added waiting-author-feedback 📭 The author of this issue needs to respond in order for us to continue investigating this issue. waiting-on-team 👋 labels Jun 5, 2023
@ghost ghost removed the waiting-author-feedback 📭 The author of this issue needs to respond in order for us to continue investigating this issue. label Jun 5, 2023
@egil egil requested review from RussKie and sebastienros June 5, 2023 09:44
@egil egil force-pushed the 3995-timeprovider-advance-multiple-invocations branch from debbca7 to 1ee526e Compare June 5, 2023 19:42
@RussKie
Copy link
Member

RussKie commented Jun 5, 2023

I had a brief chat with @sebastienros, and it looks like I may have misinterpreted his comments. I am removing myself from this PR and letting @sebastienros and @geeknoid take over the reviews.

@@ -158,28 +166,39 @@ internal void RemoveWaiter(FakeTimeProviderTimer.Waiter waiter)
}
}

private List<FakeTimeProviderTimer.Waiter> GetWaitersToWake()
private FakeTimeProviderTimer.Waiter? TryGetWaiterToWake(DateTimeOffset targetNow)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it use the standard Try... pattern by being bool TryGetWaiterToWake(DateTimeOffset targetNow, out FakeTimeProviderTimer.Waiter?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. But please indulge me, why?

I would use the common bool TryGetX(Foo foo, out Foo bar) in a public API surface since that is a very recognizable pattern in the .NET ecosystem. For private/internal stuff, I have changed to this pattern since we now have nullable reference types and pattern matching, I feel this version is more direct, clean, and doesn't involve out arguments. I am fairly certain that had these language features been around in the early days, the TryGetX pattern would not be the norm.

I do respect that you may have a coding standard in this repo you like to follow (I admit I didn't look at other projects in the repo, just this one) and I would change it regardless if you prefer the other style.

@egil
Copy link
Contributor Author

egil commented Jun 6, 2023

@sebastienros / @geeknoid I've added you to my fork of the repo so you can push changes to this PR as you see fit.

It is often useful to have the epoch/start time available
via the FakeTimeProvider during testing, as it provides a
stable offset (time-0) from which to advance or set a new
utc-now based off, e.g. to move to time-X on a timeline
starting at time-0.
@egil
Copy link
Contributor Author

egil commented Jun 6, 2023

Let me add the missing experimental attribute to the ctor and push a rewrite of the git history that bundles up the feedback into clean commits.

Ps. I do not have the permissions to merge the PR.

@egil egil force-pushed the 3995-timeprovider-advance-multiple-invocations branch from e8010ee to 8e3c86e Compare June 6, 2023 14:05
egil added 2 commits June 6, 2023 14:19
…ance

fixes dotnet#3995

Reorder variable's in comparaison

Co-authored-by: Igor Velikorossov <RussKie@users.noreply.github.com>

remove unneeded comments

Squashed commit of the following:

commit 2f51f4063e2c0ec9042d425b50380f8c81ab6838
Author: Egil Hansen <egil@assimilated.dk>
Date:   Tue May 30 16:37:13 2023 +0000

    All changes
@egil egil force-pushed the 3995-timeprovider-advance-multiple-invocations branch from 8e3c86e to 145515a Compare June 6, 2023 14:20
@geeknoid geeknoid merged commit 009b7bb into dotnet:main Jun 7, 2023
@ghost ghost removed the waiting-on-team 👋 label Jun 7, 2023
@RussKie RussKie added this to the 8.0 Preview5 milestone Jun 8, 2023
@egil egil mentioned this pull request Jun 20, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Jul 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

FakeTimeProvider.Advance/SetUtcNow does not behave as expected
4 participants